package com.example.demo.controller;

import com.example.demo.common.ResultAjax;
import com.example.demo.common.SessionUtils;
import com.example.demo.model.Articleinfo;
import com.example.demo.model.Userinfo;
import com.example.demo.model.vo.UserinfoVO;
import com.example.demo.service.ArticleService;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

@RestController
@RequestMapping("/art")
public class ArticleinfoController {
    @Autowired //属性注入,得到操作数据库的类
    private ArticleService articleService;

    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;//多线程的任务执行器(方法注入的获取方法)

    @Autowired
    private UserService userService;//调用通过uid查询用户信息的方法要使用的对象
    /**
     * 得到当前登录用户的文章列表
     * @param request
     * @return
     */
    @RequestMapping("/mylist")
    public ResultAjax myList(HttpServletRequest request){
        //1,得到当前登录用户
        Userinfo userinfo= SessionUtils.getUser(request);//获取登录用户的信息(通过刚刚写的工具类的方法)
        if (userinfo==null){
            //没有获取到信息,代表用户未登录
            return ResultAjax.fial(-1,"请先登录");
        }
        //2根据用户id来查询用户对应的文章信息
        List<Articleinfo> list=articleService.getListByuid(userinfo.getId());
        //处理list,将文章内容变成简介(截取即可)
        list.stream().parallel().forEach((art)->{
            if(art.getContent().length()>20){//比20大就截取
                art.setContent(art.getContent().substring(0,20));//0截取到20
            }
        });

        //3,返回给前端
        return ResultAjax.succ(list);//把集合数据当做data返回前端
    }

    /**
     * 根据文章id删除文章
     * @param aid
     * @param request
     * @return
     */
    @RequestMapping("/del")
    public ResultAjax del(Integer aid,HttpServletRequest request){
        //1进行测参数判断
        if (aid==null || aid<=0){
            return ResultAjax.fial(-1,"抱歉,参数有误");
        }
        //2,得到当前的登录用户(一是得到当前用户的uid,二是判断当前用户有没有登录,保险)
        Userinfo userinfo=SessionUtils.getUser(request);//这是之前写的得到当前登录用户的方法
        if (userinfo==null){
            return ResultAjax.fial(-1,"请先登录");//没有获取到当前登录用户(没有登录)
        }
        //3判断文章的归属人(uid)+删除文章 where id=#{aid} and uid=#{uid}"
        int result=articleService.del(aid, userinfo.getId());
        //4,把结果返回到前端
        return ResultAjax.succ(result);
    }
    /**
     * 添加文章
     */
    @RequestMapping("/add")
    public ResultAjax add(Articleinfo articleinfo,HttpServletRequest request){
        //1校验参数
        if(articleinfo==null || !StringUtils.hasLength(articleinfo.getTitle()) ||
                !StringUtils.hasLength(articleinfo.getContent())){//不能得到前端数据,或者标题he正文为null和""
            return ResultAjax.fial(-1,"参数有误");
        }
        //2,组装数据
        Userinfo userinfo=SessionUtils.getUser(request);//前面写的方法,通过http请求得到登录用户的信息
        if(userinfo==null){
            //没有得到,代表当前用户没有登录
            return ResultAjax.fial(-2,"请先登录");
        }
        articleinfo.setUid(userinfo.getId());//因为已经从前端得到了文章标题和正文,只要把作者id加上即可
        //3,将数据入库(数据库)
        int result=articleService.add(articleinfo);
        //4,将结果返回给前端
        return ResultAjax.succ(result);
    }

    /**
     * 通过文章id和用户uid查询文章(自己发表的文章详情
     */
    @RequestMapping("update_init")
    public ResultAjax updateInit(Integer aid,HttpServletRequest request){
        //1,校验参数
        if (aid==null || aid<=0){
            return ResultAjax.fial(-1,"参数有误");
        }
        //2,得到当前用户的uid
        Userinfo userinfo=SessionUtils.getUser(request);
        if(userinfo==null){//没获取到,代表没有登录
            return ResultAjax.fial(-2,"请先登录");
        }
        //3,查询文章并且校验权限where id=#{aid} and uid=#{uid}
        Articleinfo articleinfo=articleService.getArticleByIdAndUid(aid, userinfo.getId());//得到文章
        //4,把查询到的文章返回到前端
        return ResultAjax.succ(articleinfo);//返回的是文章表
    }

    /**
     * 修改文章
     */

    @RequestMapping("update")
    public ResultAjax update(Articleinfo articleinfo,HttpServletRequest request){
        //1,校验参数
        if (articleinfo==null||!StringUtils.hasLength(articleinfo.getContent())||!StringUtils.hasLength(articleinfo.getTitle())
        ||articleinfo.getId()==0){
            return ResultAjax.fial(-1,"参数非法");
        }
        //2,获取登录用户,检验文章id是否对应用户id
        Userinfo userinfo=SessionUtils.getUser(request);
        if(userinfo==null){//为登录
            return ResultAjax.fial(-2,"请先登录");
        }
        articleinfo.setUid(userinfo.getId());//设置用户uid
        //3,修改文章,并校验归属人
        int result=articleService.update(articleinfo);
        //4,将结果返回给前端
        return ResultAjax.succ(result);
    }
    /**
     * 查询文章详情页
     */
    @RequestMapping("/detail")
    public ResultAjax detail(Integer aid) throws ExecutionException, InterruptedException {
        //1,校验参数
        if (aid==null || aid<=0){
            return ResultAjax.fial(-1,"非法参数");
        }
        //2,查询文章详细信息
        Articleinfo articleinfo=articleService.getDatailById(aid);//通过文章id,获取信息
        if (articleinfo==null||articleinfo.getId()<=0){
            return ResultAjax.fial(-1,"非法参数");//传递来的文章id,有问题,查不到
        }
        //3根据uid查询用户详细信息
        FutureTask<UserinfoVO> userTask=new FutureTask<>(()->{
            return userService.getUserById(articleinfo.getUid());//返回通过uid查询到的用户信息
        });
        taskExecutor.submit(userTask);//把任务放到线程中执行
        //4,根据uid查询发布的博客总数
        FutureTask<Integer> artCountTask=new FutureTask<>(()->{
            return articleService.getArtCountById(articleinfo.getUid());//返回通过uid查询到的博客数量
        });
        taskExecutor.submit(artCountTask);//把任务放进线程中
        //5,组装数据
        UserinfoVO userinfoVO=userTask.get();//获取任务的执行返回值(先等待线程执行完成)
        int artCount=artCountTask.get();//获取任务的执行返回值(先等待线程执行完成)
        userinfoVO.setArtCount(artCount);//设置博客数量(查询获取到的)
        HashMap<String,Object> hashMap=new HashMap<>();//使用hashmap来存储两个返回对象
        hashMap.put("user",userinfoVO);//放入用户信息
        hashMap.put("art",articleinfo);//放入文章信息
        //6,将结果返回到前端
        return ResultAjax.succ(hashMap);//直接把hsahmap返回回去
    }
    /**
     * 阅读量设置
     */
    @RequestMapping("/increment_rcount")
    public ResultAjax incrementRcount(Integer aid){
        //1,校验参数
        if (aid==null || aid<=0){
            return ResultAjax.fial(-1,"非法参数");
        }
        //2更改数据库
        int result =articleService.incrementRCount(aid);
        //返回数据到前端
        return ResultAjax.succ(result);
    }

    /**
     * 查询分页功能
     */
    @RequestMapping("/getlistbypage")
    public ResultAjax getListByPage(Integer pindex,Integer psize) throws ExecutionException, InterruptedException {//参数是当前页数,和每一页要显示几条
        //1,参数校正
        System.out.println(pindex+"hhhhhhh");
        if(pindex==null||pindex<1){//没有传递当前页数或传递有误
            pindex=1;//就把它当做第一页
        }
        if(psize==null||psize<1){//没有传递当前每一页要显示几条或传递有误
            psize=2;//就把它当做显示两条
        }
        //2,并发进行文章列表和总页数的查询
        //2.1查询文章列表
        int finalOffset = psize*(pindex-1);//分页公式
        int finalPsize = psize;//这里之所以在外面赋值一份,是因为变量捕获
        FutureTask<List<Articleinfo>> listTask=new FutureTask<>(()->{
            return articleService.getListByPage(finalPsize, finalOffset);
        });
        //2.2查找总页数
        FutureTask<Integer> sizeTask=new FutureTask<>(()->{
            int totalCount=articleService.getCount();//得到文章总条数
            double sizeTemp=(totalCount*1.0)/(finalPsize*1.0);//得到的页数是3.33333形式的中间变量
            return (int)Math.ceil(sizeTemp);//方上取整后(4.0形式的)强转为int类型(4)

        });
        //2,3多线程并发执行
        taskExecutor.submit(listTask);
        taskExecutor.submit(sizeTask);
        //3,组装数据
        List<Articleinfo> list=listTask.get();//获取执行结果
        int size=sizeTask.get();
        HashMap<String,Object> hashMap=new HashMap<>();
        hashMap.put("list",list);
        hashMap.put("size",size);
        //4,把数据返回到前端
        return ResultAjax.succ(hashMap);
    }


}
